﻿#region Copyright(c) 2006 ZO, All right reserved.
// -----------------------------------------------------------------------------
// Copyright(c) 2006 ZO, All right reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   1.  Redistribution of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//   2.  Redistribution in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//   3.  The name of the author may not be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
#endregion


#region Using directives

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using ZO.SmartCore.Threading;

#endregion

namespace ZO.SmartCore.My4CSharp
{
    /// <summary>
    /// Provides properties for getting information about the computer's memory
    /// </summary>
    [Browsable(false)]
    [EditorBrowsable(EditorBrowsableState.Advanced)]
    public class MemoryStatus
    {

        #region Constructors
        /// <summary>
        /// Initializes a new instance of the <see cref="MemoryStatus"/> class.
        /// </summary>
        public MemoryStatus()
        {
            this.isOldOS = Environment.OSVersion.Version.Major < 5;
        }
        #endregion

        #region Destructor

        #endregion

        #region Fields

        private NativeMethods.MEMORYSTATUS memoryInfo = new NativeMethods.MEMORYSTATUS();

        private NativeMethods.MEMORYSTATUSEX memoryInfoX = new NativeMethods.MEMORYSTATUSEX();


    
        private static readonly ThreadSafeObjectProvider<MemoryStatus> thisInstance = new ThreadSafeObjectProvider<MemoryStatus>();


        /// <summary>
        /// Ooperating System is 95, 98, ME, NT
        /// </summary>
        private bool isOldOS;

        /// <summary>
        /// free physical memory
        /// </summary>
        private ulong _availablePhysicalMemory;

        /// <summary>
        /// total amount of the computer's free virtual address space
        /// </summary>
        private ulong _availableVirtualMemory;

        /// <summary>
        /// total amount of physical memory
        /// </summary>
        private ulong _totalPhysicalMemory;

        /// <summary>
        ///  total amount of virtual address space available
        /// </summary>
        private ulong _totalVirtualMemory;

        #endregion

        #region Events

        #endregion

        #region Operators

        #endregion

        #region Properties
        /// <summary>
        /// Gets the total amount of virtual address space available for the computer.
        /// </summary>
        /// <value>A ULong containing the number of bytes of virtual address space available for the computer.</value>
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public ulong TotalVirtualMemory
        {
            get
            {
                MemoryStatus helperInstance = thisInstance.Instance;

                if (helperInstance != null)
                {
                    helperInstance.Refresh();
                    return helperInstance._totalVirtualMemory;
                }
                return 0;
            }
        }

        /// <summary>
        /// Gets the total amount of free physical memory for the computer
        /// </summary>
        /// <value>A ULong containing the number of bytes of free physical memory for the computer. </value>
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public ulong AvailablePhysicalMemory
        {
            get
            {
                MemoryStatus helperInstance = thisInstance.Instance;

                if (helperInstance != null)
                {
                    helperInstance.Refresh();
                    return helperInstance._availablePhysicalMemory;
                }
                return 0;
            }
        }

        /// <summary>
        /// Gets the total amount of the computer's free virtual address space. 
        /// </summary>
        /// <value>A ULong containing the number of bytes of the computer's free virtual address space. </value>
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        [CLSCompliant(false)]
        public ulong AvailableVirtualMemory
        {
            get
            {
                MemoryStatus helperInstance = thisInstance.Instance;

                if (helperInstance != null)
                {
                    helperInstance.Refresh();
                    return helperInstance._availableVirtualMemory;
                }
                return 0;
            }
        }

        /// <summary>
        /// Gets the total amount of physical memory for the computer. 
        /// </summary>
        /// <value>A ULong containing the number of bytes of physical memory for the computer. </value>
        [CLSCompliant(false)]
        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public ulong TotalPhysicalMemory
        {
            get
            {
                MemoryStatus helperInstance = thisInstance.Instance;

                if (helperInstance != null)
                {
                    helperInstance.Refresh();
                    return helperInstance._totalPhysicalMemory;
                }
                return 0;
            }
        }
        #endregion

        #region Methods
        private void Refresh()
        {
            if (this.isOldOS)
            {
                NativeMethods.GlobalMemoryStatus(memoryInfo);
                this._totalVirtualMemory = memoryInfo.dwTotalVirtual;
                this._availablePhysicalMemory = memoryInfo.dwAvailPhys;
                this._availableVirtualMemory = memoryInfo.dwAvailVirtual;
                this._totalPhysicalMemory = memoryInfo.dwTotalPhys;
            }
            else
            {
                NativeMethods.GlobalMemoryStatusEx(memoryInfoX);
                this._totalVirtualMemory = memoryInfoX.ullTotalVirtual;
                this._availablePhysicalMemory = memoryInfoX.ullAvailPhys;
                this._availableVirtualMemory = memoryInfoX.ullAvailVirtual;
                this._totalPhysicalMemory = memoryInfoX.ullTotalPhys;
                ;
            }
        } // Refresh
        #endregion
    }
}
